Text Analysis with Voyant

Voyant Voyant-tools.org is a collection of text mining tools with a user interface. It’s a great way in to text mining.

Loading a text

Open a browser and go to https://voyant-tools.org/

### Load a pre-existing text

The front page of Voyant allows you to add texts, either one or multiple. It also has a limited selection of texts pre-loaded, so if you would prefer to load one of these and just spend some time playing around with the interface, that is a good place to start. Click ‘Open’ and choose a corpus containing the entire works of either William Shakespeare or Jane Austen. If you do this, you can skip straight to the ‘Voyant Interface’ section below, if you like.

Loading your own text

There are two ways to load your own text(s): either by entering a url to a document or by uploading a file from your own computer. We’ll use plain text files (the type created by notepad or TextEdit), but you can also upload HTML, XML, and various others (see the help file for more details).

First we need some books in plain text format. Project Gutenberg is a site containing a large database of freely-available ebooks, in a variety of formats. Let’s make a corpus containing the four Sherlock Holmes novels.

First, open a new tab in your browser, and find the book you’d like to add on the site, using the search or browse function. The book page will allow you to download the eBook in a number of formats. Once you’ve found a book of interest, right click on the ‘Plain Text UTF-8’ link, and click ‘copy the link address’ (in Chrome):

Return to the Voyant-tools tab, and paste the link into the input box. Switch back to Project Gutenberg and find the other three novels and repeat the process. Copy over the links and put one on each line:

Click ‘Reveal’ to load the texts in Voyant.

If you’re not interested in literature, or if you have a set of documents from your own research you’d like to analyse, you can add text from any URL, or from your computer. There are many sources of text files available, although in many cases, you’ll have to first download and unzip a set of files before uploading them.

Some to try include (however many of these are large files or require some additional steps, and might be best to try offline after the workshop):

The Oxford Text Archive

Follow the instructions here: https://glam-workbench.net/trove-harvester/ to bulk download text files from Australian historical newspapers.

The Enron corpus (https://www.cs.cmu.edu/~enron/) if you are interested in more recent text for analysis.

Voyant Interface

Whether you loaded a pre-existing text, or added your own, you should now be presented with the following screen:

There’s a lot going on here at first, so I’ll break it down. The screen is divided into five separate panes: three at the top and two underneath, displaying a range of standard text mining tools. Voyant has many more tools available, and you can swap out the default ones for others. If you hover over the top-right of a pane, you’ll see three new options. If you click on the windows icon (second from the left), you can select a new tool to replace the current one. You can do this for any of the windows.

The default tools are, clockwise from the top-left:

  • A word cloud (and list of top terms). A word cloud displays the most frequent words in a corpus, sized by the number of occurences. It’s a good way to get an overview of a particular text.
  • A reader with the full texts.
  • A trends tool, displaying the frequency of either the five most-common words or a selected word.
  • A ‘collocation’ tool (displays a set number of words either side of a selected word)
  • A summary of the corpus.

Some of the windows have additional pages. Click on ‘terms’ in the word-cloud (top-left) and instead of a wordcloud you’ll get a count of the occurences of the top terms.

The windows are connected to each other: for example, if you click on a word in the word cloud in the top-left window, you’ll see the frequency of that word in the trends pane on the right.

One typical text mining question is to use what’s known as the ‘type-token ratio’ to compare the writing style of a set of documents. It’s the total number of unique words (known as types) divided by the total number of words (tokens). The ratio of the two can be interpreted as the ‘richness’ of the vocabulary in a particular text.

To see this, click on the documents tab in the summary window (bottom-left by default)

We can see that there is some difference between the Sherlock Holmes novels (though we need to be careful with the interpretation: longer novels will naturally have a smaller ratio: it would be surprising if an author’s use of unique words continued to increase as they wrote longer novels. The two final novels are a very similar length and most easily comparable, and they have very similar ratios).

Spend some more time trying out Voyant tools. Swap out the default windows for some other ones, and note any interesting observations.

Text analysis with a coding language

If you’d like to get a flavour of how you can use a programming language can be used to analyse text, you have a couple of options. I’ve put together a very short demo of R in an interactive document called a ‘notebook’, here.

This notebook loads in an interactive environment called Binder. Once the link above has loaded, you’ll see an interactive document with instructions.

A third option is to use a service called Constellate, run by the Journal database Jstor. This allows you to build and analyse a corpus of JStor articles, using search terms. They take some time to initialise, so for now it’s best to use an existing one.

First, go to https://constellate.org/ and click on ‘dashboard’ on the top-right. You have the option of building a new dataset or selecting a featured dataset. For now, try out one of the featured datasets. Click ‘analyze’, and you’ll get a pop-up window containing links to a series of notebooks—interactive documents containing code and text. If you have never used Jupyter notebooks before, start with the first tutorial to learn how to use them - otherwise feel free to check out other ones more specific to text mining.

After this workshop, I can recommend playing around with the corpus builder, which will construct a dataset suitable for text mining from a set of parameters and keywords.

Section 2: Mapping

As with the above, here are three things to try out using maps, in order of difficulty.

1 - Find a map on David Rumsey

Spatial Humanities isn’t just about creating your own maps, but finding and (eventually) analysing existing, often historical ones. The site https://www.davidrumsey.com/ contains 1000s of historical maps which have mostly been ‘geo-rectified’, meaning that they have been fixed to modern coordinates. This means you can overlay over a modern map to look for changes over time.

We’ll use the ‘MapRankSearch’ feature to find a map of interest. Open https://rumsey.mapranksearch.com/ in a browser

As you scroll and zoom the map, search results on the right-hand side will reflect the area shown. You can also restrict the map dates using the slider underneath. Once you’ve found a map, click on it to open it in a picture viewer. Next, click ‘View in Georeferencer’ to open the map overlaid on a modern one. Use the slider at the top-right of this screen to turn the transparency of the old map up or down, revealing the modern map beneath.

To go even further, you can compare multiple maps at once. CLick the ‘overlay and compare’ button in the bottom-right corner, which will open the map in Georeferencer.com: here you can add more maps to the interface and change the transparency of each one.

Questions:

2 - Plot some points in Palladio

Many tasks using maps involve displaying some geographic data. To do this we can use a tool called Palladio, which was specifically made to work with humanities data. There are a number of very good tutorials for using Palladio, particularly https://miriamposner.com/blog/getting-started-with-palladio/ but in this short session we’ll use the sample data to have a look around.

First, go to http://hdlab.stanford.edu/palladio/ and click ‘start’. This is where you can load your own data in .csv format (follow the tutorial above to learn how to structure it), or else click on the ‘Try with sample data’ link on the left hand side.

The project view of Palladio will load up. The sample data is a small dataset of notable individuals, with their gender and places and dates of birth and death. Let’s map all the birthplaces in the dataset.

Click on the map tab at the top of the screen:

Next, create a ‘layer’, which will allow us to draw points of data on top of the map. Click ‘new layer’ and give it a name.

Next, tell Palladio which data to use to draw points on the map. Click on the ‘Places’ box which will give a drop-down of all the fields in the data with geographic coordinates. Click on the first one, ‘Birthplace’.

Last, we want to size the points by the number of people born in that place. Click on the size points tickbox, which will give you a couple of options for data to use for sizing. Leave it at the default, ‘Number of People’:

Click ‘Add layer’ to create the points on your map. You’ve just created a basic interactive map, congratulations! You can move the map around by clicking and dragging, and hovering over a point will display the relevant data (in this case, the number of people born in that place)

Some other things to try:

Add another layer (place of death) and compare the two.

Try out the ‘point to point’ option, using both place of birth and place of death. 3 - Use R to create a map

Network Analysis

Step 1: Load network data into Palladio

Step 2: Load network data into Network Navigator

Step 3: R library with Network Analysis (or maybe Jupyter/Google collab)

LS0tCnRpdGxlOiAiVGV4dCBBbmFseXNpcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIFRleHQgQW5hbHlzaXMgd2l0aCBWb3lhbnQKClZveWFudCAKVm95YW50LXRvb2xzLm9yZyBpcyBhIGNvbGxlY3Rpb24gb2YgdGV4dCBtaW5pbmcgdG9vbHMgd2l0aCBhIHVzZXIgaW50ZXJmYWNlLiBJdCdzIGEgZ3JlYXQgd2F5IGluIHRvIHRleHQgbWluaW5nLiAKCiMjIExvYWRpbmcgYSB0ZXh0CgpPcGVuIGEgYnJvd3NlciBhbmQgZ28gdG8gaHR0cHM6Ly92b3lhbnQtdG9vbHMub3JnLwoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW5zaG90IDIwMjEtMDUtMjEgYXQgMDguNDQuNTYucG5nKQojIyMgTG9hZCBhIHByZS1leGlzdGluZyB0ZXh0ICAKClRoZSBmcm9udCBwYWdlIG9mIFZveWFudCBhbGxvd3MgeW91IHRvIGFkZCB0ZXh0cywgZWl0aGVyIG9uZSBvciBtdWx0aXBsZS4gSXQgYWxzbyBoYXMgYSBsaW1pdGVkIHNlbGVjdGlvbiBvZiB0ZXh0cyBwcmUtbG9hZGVkLCBzbyBpZiB5b3Ugd291bGQgcHJlZmVyIHRvIGxvYWQgb25lIG9mIHRoZXNlIGFuZCBqdXN0IHNwZW5kIHNvbWUgdGltZSBwbGF5aW5nIGFyb3VuZCB3aXRoIHRoZSBpbnRlcmZhY2UsIHRoYXQgaXMgYSBnb29kIHBsYWNlIHRvIHN0YXJ0LiBDbGljayAnT3BlbicgYW5kIGNob29zZSBhIGNvcnB1cyBjb250YWluaW5nIHRoZSBlbnRpcmUgd29ya3Mgb2YgZWl0aGVyIFdpbGxpYW0gU2hha2VzcGVhcmUgb3IgSmFuZSBBdXN0ZW4uIElmIHlvdSBkbyB0aGlzLCB5b3UgY2FuIHNraXAgc3RyYWlnaHQgdG8gdGhlICdWb3lhbnQgSW50ZXJmYWNlJyBzZWN0aW9uIGJlbG93LCBpZiB5b3UgbGlrZS4KCiMjIyBMb2FkaW5nIHlvdXIgb3duIHRleHQKClRoZXJlIGFyZSB0d28gd2F5cyB0byBsb2FkIHlvdXIgb3duIHRleHQocyk6IGVpdGhlciBieSBlbnRlcmluZyBhIHVybCB0byBhIGRvY3VtZW50IG9yIGJ5IHVwbG9hZGluZyBhIGZpbGUgZnJvbSB5b3VyIG93biBjb21wdXRlci4gV2UnbGwgdXNlIHBsYWluIHRleHQgZmlsZXMgKHRoZSB0eXBlIGNyZWF0ZWQgYnkgbm90ZXBhZCBvciBUZXh0RWRpdCksIGJ1dCB5b3UgY2FuIGFsc28gdXBsb2FkIEhUTUwsIFhNTCwgYW5kIHZhcmlvdXMgb3RoZXJzIChzZWUgdGhlIFtoZWxwIGZpbGVdKGh0dHBzOi8vdm95YW50LXRvb2xzLm9yZy9kb2NzLyMhL2d1aWRlL2NvcnB1c2NyZWF0b3Itc2VjdGlvbi1pbnB1dC1mb3JtYXQpIGZvciBtb3JlIGRldGFpbHMpLgoKRmlyc3Qgd2UgbmVlZCBzb21lIGJvb2tzIGluIHBsYWluIHRleHQgZm9ybWF0LiBbUHJvamVjdCBHdXRlbmJlcmddKGh0dHBzOi8vd3d3Lmd1dGVuYmVyZy5vcmcvKSBpcyBhIHNpdGUgY29udGFpbmluZyBhIGxhcmdlIGRhdGFiYXNlIG9mIGZyZWVseS1hdmFpbGFibGUgZWJvb2tzLCBpbiBhIHZhcmlldHkgb2YgZm9ybWF0cy4gTGV0J3MgbWFrZSBhIGNvcnB1cyBjb250YWluaW5nIHRoZSBmb3VyIFNoZXJsb2NrIEhvbG1lcyBub3ZlbHMuIAoKRmlyc3QsIG9wZW4gYSBuZXcgdGFiIGluIHlvdXIgYnJvd3NlciwgYW5kIGZpbmQgdGhlIGJvb2sgeW91J2QgbGlrZSB0byBhZGQgb24gdGhlIHNpdGUsIHVzaW5nIHRoZSBzZWFyY2ggb3IgYnJvd3NlIGZ1bmN0aW9uLiBUaGUgYm9vayBwYWdlIHdpbGwgYWxsb3cgeW91IHRvIGRvd25sb2FkIHRoZSBlQm9vayBpbiBhIG51bWJlciBvZiBmb3JtYXRzLiBPbmNlIHlvdSd2ZSBmb3VuZCBhIGJvb2sgb2YgaW50ZXJlc3QsIHJpZ2h0IGNsaWNrIG9uIHRoZSAnUGxhaW4gVGV4dCBVVEYtOCcgbGluaywgYW5kIGNsaWNrICdjb3B5IHRoZSBsaW5rIGFkZHJlc3MnIChpbiBDaHJvbWUpOgoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW5zaG90IDIwMjEtMDUtMjEgYXQgMDkuMDYuNTYucG5nKQpSZXR1cm4gdG8gdGhlIFZveWFudC10b29scyB0YWIsIGFuZCBwYXN0ZSB0aGUgbGluayBpbnRvIHRoZSBpbnB1dCBib3guIFN3aXRjaCBiYWNrIHRvIFByb2plY3QgR3V0ZW5iZXJnIGFuZCBmaW5kIHRoZSBvdGhlciB0aHJlZSBub3ZlbHMgYW5kIHJlcGVhdCB0aGUgcHJvY2Vzcy4gQ29weSBvdmVyIHRoZSBsaW5rcyBhbmQgcHV0IG9uZSBvbiBlYWNoIGxpbmU6CgohW10oZGhfZGVmaW5pdGlvbnNfYm90L1NjcmVlbnNob3QgMjAyMS0wNS0yMSBhdCAwOS4wOC41Mi5wbmcpCkNsaWNrICdSZXZlYWwnIHRvIGxvYWQgdGhlIHRleHRzIGluIFZveWFudC4KCklmIHlvdSdyZSBub3QgaW50ZXJlc3RlZCBpbiBsaXRlcmF0dXJlLCBvciBpZiB5b3UgaGF2ZSBhIHNldCBvZiBkb2N1bWVudHMgZnJvbSB5b3VyIG93biByZXNlYXJjaCB5b3UnZCBsaWtlIHRvIGFuYWx5c2UsIHlvdSBjYW4gYWRkIHRleHQgZnJvbSBhbnkgVVJMLCBvciBmcm9tIHlvdXIgY29tcHV0ZXIuIFRoZXJlIGFyZSBtYW55IHNvdXJjZXMgb2YgdGV4dCBmaWxlcyBhdmFpbGFibGUsIGFsdGhvdWdoIGluIG1hbnkgY2FzZXMsIHlvdSdsbCBoYXZlIHRvIGZpcnN0IGRvd25sb2FkIGFuZCB1bnppcCBhIHNldCBvZiBmaWxlcyBiZWZvcmUgdXBsb2FkaW5nIHRoZW0uIAoKU29tZSB0byB0cnkgaW5jbHVkZSAoaG93ZXZlciBtYW55IG9mIHRoZXNlIGFyZSBsYXJnZSBmaWxlcyBvciByZXF1aXJlIHNvbWUgYWRkaXRpb25hbCBzdGVwcywgYW5kIG1pZ2h0IGJlIGJlc3QgdG8gdHJ5IG9mZmxpbmUgYWZ0ZXIgdGhlIHdvcmtzaG9wKToKCltUaGUgT3hmb3JkIFRleHQgQXJjaGl2ZV0oaHR0cHM6Ly9vdGEuYm9kbGVpYW4ub3guYWMudWsvKQoKRm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgaGVyZTogaHR0cHM6Ly9nbGFtLXdvcmtiZW5jaC5uZXQvdHJvdmUtaGFydmVzdGVyLyB0byBidWxrIGRvd25sb2FkIHRleHQgZmlsZXMgZnJvbSBBdXN0cmFsaWFuIGhpc3RvcmljYWwgbmV3c3BhcGVycy4KClRoZSBFbnJvbiBjb3JwdXMgKGh0dHBzOi8vd3d3LmNzLmNtdS5lZHUvfmVucm9uLykgaWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIG1vcmUgcmVjZW50IHRleHQgZm9yIGFuYWx5c2lzLgoKIyMgVm95YW50IEludGVyZmFjZSAgCgpXaGV0aGVyIHlvdSBsb2FkZWQgYSBwcmUtZXhpc3RpbmcgdGV4dCwgb3IgYWRkZWQgeW91ciBvd24sIHlvdSBzaG91bGQgbm93IGJlIHByZXNlbnRlZCB3aXRoIHRoZSBmb2xsb3dpbmcgc2NyZWVuOgoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW5zaG90IDIwMjEtMDUtMjEgYXQgMDkuMTIuMDQucG5nKQoKVGhlcmUncyBhIGxvdCBnb2luZyBvbiBoZXJlIGF0IGZpcnN0LCBzbyBJJ2xsIGJyZWFrIGl0IGRvd24uIFRoZSBzY3JlZW4gaXMgZGl2aWRlZCBpbnRvIGZpdmUgc2VwYXJhdGUgcGFuZXM6IHRocmVlIGF0IHRoZSB0b3AgYW5kIHR3byB1bmRlcm5lYXRoLCBkaXNwbGF5aW5nIGEgcmFuZ2Ugb2Ygc3RhbmRhcmQgdGV4dCBtaW5pbmcgdG9vbHMuIFZveWFudCBoYXMgbWFueSBtb3JlIHRvb2xzIGF2YWlsYWJsZSwgYW5kIHlvdSBjYW4gc3dhcCBvdXQgdGhlIGRlZmF1bHQgb25lcyBmb3Igb3RoZXJzLiBJZiB5b3UgaG92ZXIgb3ZlciB0aGUgdG9wLXJpZ2h0IG9mIGEgcGFuZSwgeW91J2xsIHNlZSB0aHJlZSBuZXcgb3B0aW9ucy4gSWYgeW91IGNsaWNrIG9uIHRoZSB3aW5kb3dzIGljb24gKHNlY29uZCBmcm9tIHRoZSBsZWZ0KSwgeW91IGNhbiBzZWxlY3QgYSBuZXcgdG9vbCB0byByZXBsYWNlIHRoZSBjdXJyZW50IG9uZS4gWW91IGNhbiBkbyB0aGlzIGZvciBhbnkgb2YgdGhlIHdpbmRvd3MuIAoKVGhlIGRlZmF1bHQgdG9vbHMgYXJlLCBjbG9ja3dpc2UgZnJvbSB0aGUgdG9wLWxlZnQ6IAoKKiBBIHdvcmQgY2xvdWQgKGFuZCBsaXN0IG9mIHRvcCB0ZXJtcykuIEEgd29yZCBjbG91ZCBkaXNwbGF5cyB0aGUgbW9zdCBmcmVxdWVudCB3b3JkcyBpbiBhIGNvcnB1cywgc2l6ZWQgYnkgdGhlIG51bWJlciBvZiBvY2N1cmVuY2VzLiBJdCdzIGEgZ29vZCB3YXkgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGEgcGFydGljdWxhciB0ZXh0LgoqIEEgcmVhZGVyIHdpdGggdGhlIGZ1bGwgdGV4dHMuIAoqIEEgdHJlbmRzIHRvb2wsIGRpc3BsYXlpbmcgdGhlIGZyZXF1ZW5jeSBvZiBlaXRoZXIgdGhlIGZpdmUgbW9zdC1jb21tb24gd29yZHMgb3IgYSBzZWxlY3RlZCB3b3JkLgoqIEEgJ2NvbGxvY2F0aW9uJyB0b29sIChkaXNwbGF5cyBhIHNldCBudW1iZXIgb2Ygd29yZHMgZWl0aGVyIHNpZGUgb2YgYSBzZWxlY3RlZCB3b3JkKQoqIEEgc3VtbWFyeSBvZiB0aGUgY29ycHVzLiAKCgpTb21lIG9mIHRoZSB3aW5kb3dzIGhhdmUgYWRkaXRpb25hbCBwYWdlcy4gQ2xpY2sgb24gJ3Rlcm1zJyBpbiB0aGUgd29yZC1jbG91ZCAodG9wLWxlZnQpIGFuZCBpbnN0ZWFkIG9mIGEgd29yZGNsb3VkIHlvdSdsbCBnZXQgYSBjb3VudCBvZiB0aGUgb2NjdXJlbmNlcyBvZiB0aGUgdG9wIHRlcm1zLiAKClRoZSB3aW5kb3dzIGFyZSBjb25uZWN0ZWQgdG8gZWFjaCBvdGhlcjogZm9yIGV4YW1wbGUsIGlmIHlvdSBjbGljayBvbiBhIHdvcmQgaW4gdGhlIHdvcmQgY2xvdWQgaW4gdGhlIHRvcC1sZWZ0IHdpbmRvdywgeW91J2xsIHNlZSB0aGUgZnJlcXVlbmN5IG9mIHRoYXQgd29yZCBpbiB0aGUgdHJlbmRzIHBhbmUgb24gdGhlIHJpZ2h0LiAKCk9uZSB0eXBpY2FsIHRleHQgbWluaW5nIHF1ZXN0aW9uIGlzIHRvIHVzZSB3aGF0J3Mga25vd24gYXMgdGhlICd0eXBlLXRva2VuIHJhdGlvJyB0byBjb21wYXJlIHRoZSB3cml0aW5nIHN0eWxlIG9mIGEgc2V0IG9mIGRvY3VtZW50cy4gSXQncyB0aGUgdG90YWwgbnVtYmVyIG9mICp1bmlxdWUqIHdvcmRzIChrbm93biBhcyB0eXBlcykgZGl2aWRlZCAgYnkgdGhlIHRvdGFsIG51bWJlciBvZiB3b3JkcyAodG9rZW5zKS4gVGhlIHJhdGlvIG9mIHRoZSB0d28gY2FuIGJlIGludGVycHJldGVkIGFzIHRoZSAncmljaG5lc3MnIG9mIHRoZSB2b2NhYnVsYXJ5IGluIGEgcGFydGljdWxhciB0ZXh0LiAgCgpUbyBzZWUgdGhpcywgY2xpY2sgb24gdGhlIGRvY3VtZW50cyB0YWIgaW4gdGhlIHN1bW1hcnkgd2luZG93IChib3R0b20tbGVmdCBieSBkZWZhdWx0KQoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW5zaG90IDIwMjEtMDUtMjEgYXQgMDkuNDEuNDMucG5nKQoKV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIHNvbWUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBTaGVybG9jayBIb2xtZXMgbm92ZWxzICh0aG91Z2ggd2UgbmVlZCB0byBiZSBjYXJlZnVsIHdpdGggdGhlIGludGVycHJldGF0aW9uOiBsb25nZXIgbm92ZWxzIHdpbGwgbmF0dXJhbGx5IGhhdmUgYSBzbWFsbGVyIHJhdGlvOiBpdCB3b3VsZCBiZSBzdXJwcmlzaW5nIGlmIGFuIGF1dGhvcidzIHVzZSBvZiB1bmlxdWUgd29yZHMgY29udGludWVkIHRvIGluY3JlYXNlIGFzIHRoZXkgd3JvdGUgbG9uZ2VyIG5vdmVscy4gVGhlIHR3byBmaW5hbCBub3ZlbHMgYXJlIGEgdmVyeSBzaW1pbGFyIGxlbmd0aCBhbmQgbW9zdCBlYXNpbHkgY29tcGFyYWJsZSwgYW5kIHRoZXkgaGF2ZSB2ZXJ5IHNpbWlsYXIgcmF0aW9zKS4KClNwZW5kIHNvbWUgbW9yZSB0aW1lIHRyeWluZyBvdXQgVm95YW50IHRvb2xzLiBTd2FwIG91dCB0aGUgZGVmYXVsdCB3aW5kb3dzIGZvciBzb21lIG90aGVyIG9uZXMsIGFuZCBub3RlIGFueSBpbnRlcmVzdGluZyBvYnNlcnZhdGlvbnMuCgojIFRleHQgYW5hbHlzaXMgd2l0aCBhIGNvZGluZyBsYW5ndWFnZQoKSWYgeW91J2QgbGlrZSB0byBnZXQgYSBmbGF2b3VyIG9mIGhvdyB5b3UgY2FuIHVzZSBhIHByb2dyYW1taW5nIGxhbmd1YWdlIGNhbiBiZSB1c2VkIHRvIGFuYWx5c2UgdGV4dCwgeW91IGhhdmUgYSBjb3VwbGUgb2Ygb3B0aW9ucy4gSSd2ZSBwdXQgdG9nZXRoZXIgYSB2ZXJ5IHNob3J0IGRlbW8gb2YgUiBpbiBhbiBpbnRlcmFjdGl2ZSBkb2N1bWVudCBjYWxsZWQgYSAnbm90ZWJvb2snLCBoZXJlLiAKClRoaXMgbm90ZWJvb2sgbG9hZHMgaW4gYW4gaW50ZXJhY3RpdmUgZW52aXJvbm1lbnQgY2FsbGVkIEJpbmRlci4gT25jZSB0aGUgbGluayBhYm92ZSBoYXMgbG9hZGVkLCB5b3UnbGwgc2VlIGFuIGludGVyYWN0aXZlIGRvY3VtZW50IHdpdGggaW5zdHJ1Y3Rpb25zLiAKCkEgdGhpcmQgb3B0aW9uIGlzIHRvIHVzZSBhIHNlcnZpY2UgY2FsbGVkIENvbnN0ZWxsYXRlLCBydW4gYnkgdGhlIEpvdXJuYWwgZGF0YWJhc2UgSnN0b3IuIFRoaXMgYWxsb3dzIHlvdSB0byBidWlsZCBhbmQgYW5hbHlzZSBhIGNvcnB1cyBvZiBKU3RvciBhcnRpY2xlcywgdXNpbmcgc2VhcmNoIHRlcm1zLiBUaGV5IHRha2Ugc29tZSB0aW1lIHRvIGluaXRpYWxpc2UsIHNvIGZvciBub3cgaXQncyBiZXN0IHRvIHVzZSBhbiBleGlzdGluZyBvbmUuIAoKRmlyc3QsIGdvIHRvIGh0dHBzOi8vY29uc3RlbGxhdGUub3JnLyBhbmQgY2xpY2sgb24gJ2Rhc2hib2FyZCcgb24gdGhlIHRvcC1yaWdodC4gWW91IGhhdmUgdGhlIG9wdGlvbiBvZiBidWlsZGluZyBhIG5ldyBkYXRhc2V0IG9yIHNlbGVjdGluZyBhIGZlYXR1cmVkIGRhdGFzZXQuIEZvciBub3csIHRyeSBvdXQgb25lIG9mIHRoZSBmZWF0dXJlZCBkYXRhc2V0cy4gQ2xpY2sgJ2FuYWx5emUnLCBhbmQgeW91J2xsIGdldCBhIHBvcC11cCB3aW5kb3cgY29udGFpbmluZyBsaW5rcyB0byBhIHNlcmllcyBvZiBub3RlYm9va3PigJRpbnRlcmFjdGl2ZSBkb2N1bWVudHMgY29udGFpbmluZyBjb2RlIGFuZCB0ZXh0LiBJZiB5b3UgaGF2ZSBuZXZlciB1c2VkIEp1cHl0ZXIgbm90ZWJvb2tzIGJlZm9yZSwgc3RhcnQgd2l0aCB0aGUgZmlyc3QgdHV0b3JpYWwgdG8gbGVhcm4gaG93IHRvIHVzZSB0aGVtIC0gb3RoZXJ3aXNlIGZlZWwgZnJlZSB0byBjaGVjayBvdXQgb3RoZXIgb25lcyBtb3JlIHNwZWNpZmljIHRvIHRleHQgbWluaW5nLiAKCkFmdGVyIHRoaXMgd29ya3Nob3AsIEkgY2FuIHJlY29tbWVuZCBwbGF5aW5nIGFyb3VuZCB3aXRoIHRoZSBjb3JwdXMgYnVpbGRlciwgd2hpY2ggd2lsbCBjb25zdHJ1Y3QgYSBkYXRhc2V0IHN1aXRhYmxlIGZvciB0ZXh0IG1pbmluZyBmcm9tIGEgc2V0IG9mIHBhcmFtZXRlcnMgYW5kIGtleXdvcmRzLgoKCgojIFNlY3Rpb24gMjogTWFwcGluZwoKQXMgd2l0aCB0aGUgYWJvdmUsIGhlcmUgYXJlIHRocmVlIHRoaW5ncyB0byB0cnkgb3V0IHVzaW5nIG1hcHMsIGluIG9yZGVyIG9mIGRpZmZpY3VsdHkuIAoKIyMgMSAtIEZpbmQgYSBtYXAgb24gRGF2aWQgUnVtc2V5CgpTcGF0aWFsIEh1bWFuaXRpZXMgaXNuJ3QganVzdCBhYm91dCBjcmVhdGluZyB5b3VyIG93biBtYXBzLCBidXQgZmluZGluZyBhbmQgKGV2ZW50dWFsbHkpIGFuYWx5c2luZyBleGlzdGluZywgb2Z0ZW4gaGlzdG9yaWNhbCBvbmVzLiBUaGUgc2l0ZSBodHRwczovL3d3dy5kYXZpZHJ1bXNleS5jb20vIGNvbnRhaW5zIDEwMDBzIG9mIGhpc3RvcmljYWwgbWFwcyB3aGljaCBoYXZlIG1vc3RseSBiZWVuICdnZW8tcmVjdGlmaWVkJywgbWVhbmluZyB0aGF0IHRoZXkgaGF2ZSBiZWVuIGZpeGVkIHRvIG1vZGVybiBjb29yZGluYXRlcy4gVGhpcyBtZWFucyB5b3UgY2FuIG92ZXJsYXkgb3ZlciBhIG1vZGVybiBtYXAgdG8gbG9vayBmb3IgY2hhbmdlcyBvdmVyIHRpbWUuIAoKV2UnbGwgdXNlIHRoZSAnTWFwUmFua1NlYXJjaCcgZmVhdHVyZSB0byBmaW5kIGEgbWFwIG9mIGludGVyZXN0LiBPcGVuIGh0dHBzOi8vcnVtc2V5Lm1hcHJhbmtzZWFyY2guY29tLyBpbiBhIGJyb3dzZXIKCiFbXShkaF9kZWZpbml0aW9uc19ib3QvU2NyZWVuIFNob3QgMjAyMS0wNS0yMSBhdCAxMi4yNy40MC5wbmcpCgpBcyB5b3Ugc2Nyb2xsIGFuZCB6b29tIHRoZSBtYXAsIHNlYXJjaCByZXN1bHRzIG9uIHRoZSByaWdodC1oYW5kIHNpZGUgd2lsbCByZWZsZWN0IHRoZSBhcmVhIHNob3duLiBZb3UgY2FuIGFsc28gcmVzdHJpY3QgdGhlIG1hcCBkYXRlcyB1c2luZyB0aGUgc2xpZGVyIHVuZGVybmVhdGguIE9uY2UgeW91J3ZlIGZvdW5kIGEgbWFwLCBjbGljayBvbiBpdCB0byBvcGVuIGl0IGluIGEgcGljdHVyZSB2aWV3ZXIuIE5leHQsIGNsaWNrICdWaWV3IGluIEdlb3JlZmVyZW5jZXInIHRvIG9wZW4gdGhlIG1hcCBvdmVybGFpZCBvbiBhIG1vZGVybiBvbmUuIFVzZSB0aGUgc2xpZGVyIGF0IHRoZSB0b3AtcmlnaHQgb2YgdGhpcyBzY3JlZW4gdG8gdHVybiB0aGUgdHJhbnNwYXJlbmN5IG9mIHRoZSBvbGQgbWFwIHVwIG9yIGRvd24sIHJldmVhbGluZyB0aGUgbW9kZXJuIG1hcCBiZW5lYXRoLgoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW4gU2hvdCAyMDIxLTA1LTIxIGF0IDEyLjI5LjUyLnBuZykKClRvIGdvIGV2ZW4gZnVydGhlciwgeW91IGNhbiBjb21wYXJlIG11bHRpcGxlIG1hcHMgYXQgb25jZS4gQ0xpY2sgdGhlICdvdmVybGF5IGFuZCBjb21wYXJlJyBidXR0b24gaW4gdGhlIGJvdHRvbS1yaWdodCBjb3JuZXIsIHdoaWNoIHdpbGwgb3BlbiB0aGUgbWFwIGluIEdlb3JlZmVyZW5jZXIuY29tOiBoZXJlIHlvdSBjYW4gYWRkIG1vcmUgbWFwcyB0byB0aGUgaW50ZXJmYWNlIGFuZCBjaGFuZ2UgdGhlIHRyYW5zcGFyZW5jeSBvZiBlYWNoIG9uZS4KCiFbXShkaF9kZWZpbml0aW9uc19ib3QvU2NyZWVuIFNob3QgMjAyMS0wNS0yMSBhdCAxMi4zMi4xMi5wbmcpClF1ZXN0aW9uczoKCgojIyAyIC0gUGxvdCBzb21lIHBvaW50cyBpbiBQYWxsYWRpbwoKTWFueSB0YXNrcyB1c2luZyBtYXBzIGludm9sdmUgZGlzcGxheWluZyBzb21lIGdlb2dyYXBoaWMgZGF0YS4gVG8gZG8gdGhpcyB3ZSBjYW4gdXNlIGEgdG9vbCBjYWxsZWQgUGFsbGFkaW8sIHdoaWNoIHdhcyBzcGVjaWZpY2FsbHkgbWFkZSB0byB3b3JrIHdpdGggaHVtYW5pdGllcyBkYXRhLiBUaGVyZSBhcmUgYSBudW1iZXIgb2YgdmVyeSBnb29kIHR1dG9yaWFscyBmb3IgdXNpbmcgUGFsbGFkaW8sIHBhcnRpY3VsYXJseSBodHRwczovL21pcmlhbXBvc25lci5jb20vYmxvZy9nZXR0aW5nLXN0YXJ0ZWQtd2l0aC1wYWxsYWRpby8gYnV0IGluIHRoaXMgc2hvcnQgc2Vzc2lvbiB3ZSdsbCB1c2UgdGhlIHNhbXBsZSBkYXRhIHRvIGhhdmUgYSBsb29rIGFyb3VuZC4KCkZpcnN0LCBnbyB0byBodHRwOi8vaGRsYWIuc3RhbmZvcmQuZWR1L3BhbGxhZGlvLyBhbmQgY2xpY2sgJ3N0YXJ0Jy4gVGhpcyBpcyB3aGVyZSB5b3UgY2FuIGxvYWQgeW91ciBvd24gZGF0YSBpbiAuY3N2IGZvcm1hdCAoZm9sbG93IHRoZSB0dXRvcmlhbCBhYm92ZSB0byBsZWFybiBob3cgdG8gc3RydWN0dXJlIGl0KSwgb3IgZWxzZSBjbGljayBvbiB0aGUgJ1RyeSB3aXRoIHNhbXBsZSBkYXRhJyBsaW5rIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZS4KClRoZSBwcm9qZWN0IHZpZXcgb2YgUGFsbGFkaW8gd2lsbCBsb2FkIHVwLiBUaGUgc2FtcGxlIGRhdGEgaXMgYSBzbWFsbCBkYXRhc2V0IG9mIG5vdGFibGUgaW5kaXZpZHVhbHMsIHdpdGggdGhlaXIgZ2VuZGVyIGFuZCBwbGFjZXMgYW5kIGRhdGVzIG9mIGJpcnRoIGFuZCBkZWF0aC4gTGV0J3MgbWFwIGFsbCB0aGUgYmlydGhwbGFjZXMgaW4gdGhlIGRhdGFzZXQuIAoKQ2xpY2sgb24gdGhlIG1hcCB0YWIgYXQgdGhlIHRvcCBvZiB0aGUgc2NyZWVuOgoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW4gU2hvdCAyMDIxLTA1LTIxIGF0IDEyLjUyLjUyLnBuZykKTmV4dCwgY3JlYXRlIGEgJ2xheWVyJywgd2hpY2ggd2lsbCBhbGxvdyB1cyB0byBkcmF3IHBvaW50cyBvZiBkYXRhIG9uIHRvcCBvZiB0aGUgbWFwLiBDbGljayAnbmV3IGxheWVyJyBhbmQgZ2l2ZSBpdCBhIG5hbWUuIAoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW4gU2hvdCAyMDIxLTA1LTIxIGF0IDEyLjU0LjIwLnBuZykKCk5leHQsIHRlbGwgUGFsbGFkaW8gd2hpY2ggZGF0YSB0byB1c2UgdG8gZHJhdyBwb2ludHMgb24gdGhlIG1hcC4gQ2xpY2sgb24gdGhlICdQbGFjZXMnIGJveCB3aGljaCB3aWxsIGdpdmUgYSBkcm9wLWRvd24gb2YgYWxsIHRoZSBmaWVsZHMgaW4gdGhlIGRhdGEgd2l0aCBnZW9ncmFwaGljIGNvb3JkaW5hdGVzLiBDbGljayBvbiB0aGUgZmlyc3Qgb25lLCAnQmlydGhwbGFjZScuCgohW10oZGhfZGVmaW5pdGlvbnNfYm90L1NjcmVlbiBTaG90IDIwMjEtMDUtMjEgYXQgMTIuNTUuMzYucG5nKQoKTGFzdCwgd2Ugd2FudCB0byBzaXplIHRoZSBwb2ludHMgYnkgdGhlIG51bWJlciBvZiBwZW9wbGUgYm9ybiBpbiB0aGF0IHBsYWNlLiBDbGljayBvbiB0aGUgc2l6ZSBwb2ludHMgdGlja2JveCwgd2hpY2ggd2lsbCBnaXZlIHlvdSBhIGNvdXBsZSBvZiBvcHRpb25zIGZvciBkYXRhIHRvIHVzZSBmb3Igc2l6aW5nLiBMZWF2ZSBpdCBhdCB0aGUgZGVmYXVsdCwgJ051bWJlciBvZiBQZW9wbGUnOgoKIVtdKGRoX2RlZmluaXRpb25zX2JvdC9TY3JlZW4gU2hvdCAyMDIxLTA1LTIxIGF0IDEyLjU2LjQzLnBuZykKQ2xpY2sgJ0FkZCBsYXllcicgdG8gY3JlYXRlIHRoZSBwb2ludHMgb24geW91ciBtYXAuIFlvdSd2ZSBqdXN0IGNyZWF0ZWQgYSBiYXNpYyBpbnRlcmFjdGl2ZSBtYXAsIGNvbmdyYXR1bGF0aW9ucyEgWW91IGNhbiBtb3ZlIHRoZSBtYXAgYXJvdW5kIGJ5IGNsaWNraW5nIGFuZCBkcmFnZ2luZywgYW5kIGhvdmVyaW5nIG92ZXIgYSBwb2ludCB3aWxsIGRpc3BsYXkgdGhlIHJlbGV2YW50IGRhdGEgKGluIHRoaXMgY2FzZSwgdGhlIG51bWJlciBvZiBwZW9wbGUgYm9ybiBpbiB0aGF0IHBsYWNlKQoKU29tZSBvdGhlciB0aGluZ3MgdG8gdHJ5OgoKQWRkIGFub3RoZXIgbGF5ZXIgKHBsYWNlIG9mIGRlYXRoKSBhbmQgY29tcGFyZSB0aGUgdHdvLiAKClRyeSBvdXQgdGhlICdwb2ludCB0byBwb2ludCcgb3B0aW9uLCB1c2luZyBib3RoIHBsYWNlIG9mIGJpcnRoIGFuZCBwbGFjZSBvZiBkZWF0aC4KMyAtIFVzZSBSIHRvIGNyZWF0ZSBhIG1hcAoKIyBOZXR3b3JrIEFuYWx5c2lzCgpTdGVwIDE6IExvYWQgbmV0d29yayBkYXRhIGludG8gUGFsbGFkaW8KClN0ZXAgMjogTG9hZCBuZXR3b3JrIGRhdGEgaW50byBOZXR3b3JrIE5hdmlnYXRvcgoKU3RlcCAzOiBSIGxpYnJhcnkgd2l0aCBOZXR3b3JrIEFuYWx5c2lzIChvciBtYXliZSBKdXB5dGVyL0dvb2dsZSBjb2xsYWIp